Dynamic Programming / Mountain Range

#include <bits/stdc++.h>
using namespace std;

using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using isize = ptrdiff_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using usize = size_t;
using f32 = float_t;
using f64 = double_t;

inline constexpr i32 Modulus = 1e9 + 7;

struct Mountain
{
    u32 Position;
    u32 Height;

    bool operator<(const Mountain& other) const
    {
        return Height > other.Height;
    }
};

int main(void)
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    u32 n;
    cin >> n;

    vector<Mountain> mountains(n);
    for (u32 position = 1; position <= n; position += 1)
    {
        u32 height;
        cin >> height;
        mountains[position - 1] = {position, height};
    }

    sort(mountains.begin(), mountains.end());
    vector<u32> dp(n + 1);

    u32 lastHeight = 0;
    set<u32> lastPositions, lookupPositions;
    for (auto [position, height] : mountains)
    {
        if (height != lastHeight)
        {
            lookupPositions.merge(lastPositions);
            lastPositions.clear();
        }

        auto iter = lookupPositions.lower_bound(position);

        u32 right = (iter == lookupPositions.end()) ? 0 : dp[*iter];
        u32 left = (iter == lookupPositions.begin()) ? 0 : dp[*--iter];

        dp[position] = max(left, right) + 1;
        lastPositions.insert(position);
        lastHeight = height;
    }

    u32 answer = *max_element(dp.begin(), dp.end());
    cout << answer;

    return 0;
}